package com.qn.example.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qn.example.mapper.CategoryMapper;
import com.qn.example.mapper.DishFlavorMapper;
import com.qn.example.mapper.DishMapper;
import com.qn.example.pojo.*;
import com.qn.example.pojo.dto.DishDto;
import com.qn.example.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 21276
 * @version 1.0
 * @date 2023/5/5 10:06
 */
@Slf4j
@Service
public class DishServiceImpl implements DishService {

    @Autowired(required = false)
    private DishMapper dishMapper;

    @Autowired(required = false)
    private DishFlavorMapper dishFlavorMapper;

    @Autowired(required = false)
    private CategoryMapper categoryMapper;


    /**
     * 菜品分页列表
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public Page<DishDto> findByPage(Integer page, Integer pageSize, String name) {
        //1. 设置当前页与页面大小
        PageHelper.startPage(page, pageSize);

        //2. 查询页面的数据 List<Dish>
        List<Dish> dishList = dishMapper.findByPage(name);

        //3. 构建一个PageInfo
        PageInfo<Dish> pageInfo = new PageInfo<>(dishList);

        //3. 把List<Dish>转换为 List<DishDto>
      /*  List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : dishList) {
            DishDto dishDto = new DishDto();
            //如果两个实体类的属性名与类型都一致的情况，我们可以使用Spring提供的工具类
            BeanUtils.copyProperties(dish,dishDto); //属性拷贝
            //根据菜品的类别的id查询类别
            Category category = categoryDao.findById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());
            dishDtoList.add(dishDto);
        }*/


        //使用jdk8的Stream流， Stream的作用：简化集合与数组的操作   map方法：对集合的元素进行类型转换
        List<DishDto> dishDtoList = dishList.stream().map(dish -> {
            DishDto dishDto = new DishDto();
            //如果两个实体类的属性名与类型都一致的情况，我们可以使用Spring提供的工具类
            BeanUtils.copyProperties(dish, dishDto); //属性拷贝
            //根据菜品的类别的id查询类别
            Category category = categoryMapper.findById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());
            return dishDto;
        }).collect(Collectors.toList());


        //5. 把PageInfo转换为Page对象
        Page<DishDto> pageResult = new Page<>(dishDtoList, pageInfo.getTotal(), pageInfo.getPageSize(), pageInfo.getPageNum());

        return pageResult;
    }


    @Transactional
    @Override
    public void save(DishDto dishDto) {
        //1. 补全菜品的数据
        dishDto.setStatus(1); // 1代表菜品启用  0代表下架商品
        dishDto.setSort(0);
        dishDto.setCreateTime(LocalDateTime.now());
        dishDto.setUpdateTime(LocalDateTime.now());
        //2.保存菜品
        dishMapper.save(dishDto);

        //3.得到菜品的口味信息
        List<DishFlavor> flavorList = dishDto.getFlavors(); //集合
        //4. 给一个口味信息补全
        for (DishFlavor dishFlavor : flavorList) {
            dishFlavor.setDishId(dishDto.getId()); //口味对应的菜品的id
            dishFlavor.setCreateTime(dishDto.getCreateTime());
            dishFlavor.setUpdateTime(dishDto.getUpdateTime());
            dishFlavor.setUpdateUser(dishDto.getUpdateUser());
            dishFlavor.setCreateUser(dishDto.getCreateUser());
            dishFlavor.setIsDeleted(0);
        }

        //5. 批量插入菜品口味
        dishFlavorMapper.batchSave(flavorList);

        //清理某个分类下面的菜品缓存数据
        Set key =  redisTemplate.keys("dish_*");
        redisTemplate.delete(key);
    }

    @Override
    public DishDto findById(Long id) {
        //1. 根据菜品的id查询菜品信息
        Dish dish = dishMapper.findById(id);
        //2. 根据菜品的id查询菜品对应口味信息
        List<DishFlavor> dishFlavorList = dishFlavorMapper.findByDishId(id);
        //3. 把菜品信息与口味信息封装成DishDto
        DishDto dishDto = new DishDto();
        //属性拷贝  源
        BeanUtils.copyProperties(dish, dishDto);
        //设置口味信息
        dishDto.setFlavors(dishFlavorList);
        return dishDto;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDish(DishDto dishDto) {
        //1. 更新时间
        dishDto.setUpdateTime(LocalDateTime.now());
        //2.更新菜品
        dishMapper.updateDish(dishDto);

        //3.删除菜品的口味(先删除之前的口味，在添加新的口味)
        dishFlavorMapper.deleteByDishId(dishDto.getId());

        //4. 得到当前菜品最新口味，然后补全数据
        List<DishFlavor> flavorList = dishDto.getFlavors();
        for (DishFlavor dishFlavor : flavorList) {
            dishFlavor.setDishId(dishDto.getId()); //口味对应的菜品的id
            dishFlavor.setCreateTime(dishDto.getCreateTime());
            dishFlavor.setUpdateTime(dishDto.getUpdateTime());
            dishFlavor.setUpdateUser(dishDto.getUpdateUser());
            dishFlavor.setCreateUser(dishDto.getCreateUser());
            dishFlavor.setIsDeleted(0);
        }
        //5. 批量插入口味信息
        dishFlavorMapper.batchSave(flavorList);

        //清理某个分类下面的菜品缓存数据
        Set key =  redisTemplate.keys("dish_*");
        redisTemplate.delete(key);
    }

    @Override
    public void delete(List<Long> ids) {
        System.err.print("批量删除的菜品id为：");
        ids.forEach(System.err::println);
        //点击删除，先删除菜品口味，最后删除菜品信息！
        dishFlavorMapper.deleteByDishIds(ids);
        dishMapper.deleteids(ids);

        //清理某个分类下面的菜品缓存数据
        Set key =  redisTemplate.keys("dish_*");
        redisTemplate.delete(key);
    }

    @Override
    public void dishStatusByStatus(Integer status, List<Long> ids) {
        //修改时间
        LocalDateTime now = LocalDateTime.now();
        dishMapper.dishStatusByStatus(status, ids, now);
    }

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public List<DishDto> list(Long categoryId, Integer status) {
        //获取存储字符串的对象
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //从缓存中获取菜品，如果有则直接返回
        String key = "dish_" + categoryId + "_" + status;
        List<DishDto> list = null;
        //如果没有，则查询数据库返回，并存储到缓存中
        Object o = valueOperations.get(key);

        if (o != null) {
            log.info("缓存对象:" + o);
            list = (List<DishDto>) o;
        } else {
            List<Dish> dishList = dishMapper.findByCategoryId(categoryId, status);
            //遍历所有的菜品，然后查询每一个菜品对应的口味，然后封装到DTO里面
            list = dishList.stream().map(dish -> {
                DishDto dishDto = new DishDto();
                //属性拷贝
                BeanUtils.copyProperties(dish, dishDto);
                //查询菜品对应口味
                List<DishFlavor> flavorList = dishFlavorMapper.findByDishId(dish.getId());
                dishDto.setFlavors(flavorList);
                return dishDto;
            }).collect(Collectors.toList());

            //存储缓存
            valueOperations.set(key, list, 1, TimeUnit.DAYS);
        }
        return list;
    }
}
